package com.example.nacos.utils;


import com.example.nacos.config.SeparatorAnnotation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 通用行映射工具类
 * 支持多种格式的文本行到对象的映射转换
 */
@Slf4j
public class LineMapper {

    /**
     * 将分隔符分隔的文本行映射为指定类型的对象
     *
     * @param line 文本行
     * @param delimiter 分隔符，如逗号、制表符等
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 映射后的对象
     */
    public static <T> T mapLineToObject(String line, String delimiter, Class<T> clazz) {
        if (line == null || line.trim().isEmpty()) {
            return null;
        }
        String[] values = null;
        try {
            T obj = clazz.getDeclaredConstructor().newInstance();
            values = line.split(Pattern.quote(delimiter), -1);
            Field[] fields = clazz.getDeclaredFields();

            for (int i = 0; i < Math.min(values.length, fields.length); i++) {
                Field field = fields[i];
                field.setAccessible(true);
                Order order = field.getAnnotation(Order.class);
                if (order == null) {
                    continue;
                }
                log.info("映射字段：" + field.getName() + " order值为：" + order.value());
                String value = values[order.value()].trim();

                setFieldValue(obj, field, value);
            }

            return obj;
        } catch (Exception e) {
            log.error("映射对象时出错: {}",values , e);
            return null;
        }
    }

    /**
     * 将固定格式的文本行映射为对象
     *
     * @param line 文本行
     * @param format 格式描述，如 "10s8s12s" 表示前10字符、接着8字符、接着12字符
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 映射后的对象
     */
    public static <T> T mapFixedWidthLine(String line, String format, Class<T> clazz) {
        if (line == null || line.trim().isEmpty()) {
            return null;
        }

        try {
            T obj = clazz.getDeclaredConstructor().newInstance();
            Field[] fields = clazz.getDeclaredFields();
            int currentPos = 0;

            String[] parts = format.split(" ");
            for (int i = 0; i < Math.min(parts.length, fields.length); i++) {
                String part = parts[i];
                int length = Integer.parseInt(part.substring(0, part.length() - 1));

                if (currentPos + length <= line.length()) {
                    String value = line.substring(currentPos, currentPos + length).trim();
                    Field field = fields[i];
                    field.setAccessible(true);

                    setFieldValue(obj, field, value);
                    currentPos += length;
                }
            }

            return obj;
        } catch (Exception e) {
            System.err.println("映射固定宽度行时出错: " + e.getMessage());
            return null;
        }
    }

    /**
     * 将正则表达式匹配的文本行映射为对象
     *
     * @param line 文本行
     * @param regex 正则表达式，必须包含捕获组
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 映射后的对象
     */
    public static <T> T mapRegexLine(String line, String regex, Class<T> clazz) {
        if (line == null || line.trim().isEmpty()) {
            return null;
        }

        try {
            java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regex);
            java.util.regex.Matcher matcher = pattern.matcher(line);

            if (matcher.matches()) {
                T obj = clazz.getDeclaredConstructor().newInstance();
                Field[] fields = clazz.getDeclaredFields();

                for (int i = 0; i < Math.min(matcher.groupCount(), fields.length); i++) {
                    Field field = fields[i];
                    field.setAccessible(true);
                    String value = matcher.group(i + 1).trim();

                    setFieldValue(obj, field, value);
                }

                return obj;
            }
        } catch (Exception e) {
            System.err.println("正则表达式映射时出错: " + e.getMessage());
        }

        return null;
    }

    /**
     * 批量映射文本行到对象列表
     *
     * @param lines 文本行列表
     * @param delimiter 分隔符
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 对象列表
     */
    public static <T> List<T> mapLinesToObjects(List<String> lines, String delimiter, Class<T> clazz) {
        List<T> result = new ArrayList<>();
        for (String line : lines) {
            T obj = mapLineToObject(line, delimiter, clazz);
            if (obj != null) {
                result.add(obj);
            }
        }
        return result;
    }

    /**
     * 设置字段值
     */
    private static <T> void setFieldValue(T obj, Field field, String value) throws IllegalAccessException {
        if (value == null || value.isEmpty()) {
            return;
        }

        Class<?> fieldType = field.getType();

        try {
            if (fieldType == String.class) {
                field.set(obj, value);
            } else if (fieldType == Integer.class || fieldType == int.class) {
                field.set(obj, Integer.parseInt(value));
            } else if (fieldType == Double.class || fieldType == double.class) {
                field.set(obj, Double.parseDouble(value));
            } else if (fieldType == Float.class || fieldType == float.class) {
                field.set(obj, Float.parseFloat(value));
            } else if (fieldType == Long.class || fieldType == long.class) {
                field.set(obj, Long.parseLong(value));
            } else if (fieldType == Boolean.class || fieldType == boolean.class) {
                field.set(obj, Boolean.parseBoolean(value) || "1".equals(value) || "Y".equalsIgnoreCase(value));
            } else if (fieldType == LocalDate.class) {
                // 尝试多种日期格式
                LocalDate dateValue = parseLocalDate(value);
                if (dateValue != null) {
                    field.set(obj, dateValue);
                }
            } else if (fieldType.isEnum()) {
                Object[] enumConstants = fieldType.getEnumConstants();
                for (Object constant : enumConstants) {
                    if (constant.toString().equalsIgnoreCase(value)) {
                        field.set(obj, constant);
                        break;
                    }
                }
            }
        } catch (NumberFormatException e) {
            System.err.println("字段 '" + field.getName() + "' 值 '" + value + "' 格式转换错误");
        }
    }

    /**
     * 解析本地日期，支持多种格式
     */
    private static LocalDate parseLocalDate(String value) {
        DateTimeFormatter[] formatters = {
                DateTimeFormatter.ISO_LOCAL_DATE,
                DateTimeFormatter.ofPattern("yyyy-MM-dd"),
                DateTimeFormatter.ofPattern("dd/MM/yyyy"),
                DateTimeFormatter.ofPattern("MM/dd/yyyy"),
                DateTimeFormatter.ofPattern("yyyyMMdd")
        };

        for (DateTimeFormatter formatter : formatters) {
            try {
                return LocalDate.parse(value, formatter);
            } catch (Exception e) {
                // 继续尝试下一种格式
            }
        }

        return null;
    }

    /**
     * 演示用法的主方法
     */
    public static void main(String[] args) {
        System.out.println("=== mapLineToObject 演示 ===");

        // 示例1: CSV格式映射
        String csvLine = "001,张三,25,7500.50,true,2025-10-28";
        Person person = mapLineToObject(csvLine, ",", Person.class);
        System.out.println("CSV映射结果: " + person);

        // 示例2: 固定宽度格式映射
//        String fixedLine = "001   张三    25   7500.50true    2025-10-28";
//        Person fixedPerson = mapFixedWidthLine(fixedLine, "6s8s4s8s6s12s", Person.class);
//        System.out.println("固定宽度映射结果: " + fixedPerson);

        // 示例3: 正则表达式映射
//        String regexLine = "ID:001, Name:张三, Age:25, Salary:7500.50, Active:true, Date:2025-10-28";
//        String regex = "ID:(\\w+),\\s*Name:(\\w+),\\s*Age:(\\d+),\\s*Salary:(\\d+\\.\\d+),\\s*Active:(\\w+),\\s*Date:(\\d{4}-\\d{2}-\\d{2})";
//        Person regexPerson = mapRegexLine(regexLine, regex, Person.class);
//        System.out.println("正则表达式映射结果: " + regexPerson);

        // 示例4: 批量映射
        List<String> lines = new ArrayList<>();
        lines.add("001,张三,25,7500.50,true,2025-10-28");
        lines.add("002,李四,30,8500.75,false,2025-10-27");
        List<Person> persons = mapLinesToObjects(lines, ",", Person.class);
        System.out.println("批量映射结果:");
        persons.forEach(System.out::println);
    }

    /**
     * 示例实体类
     */
    public static class Person {
        private String id;
        private String name;
        private Integer age;
        private Double salary;
        private Boolean active;
        private LocalDate date;

        public Person() {}

        public Person(String id, String name, Integer age, Double salary, Boolean active, LocalDate date) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.salary = salary;
            this.active = active;
            this.date = date;
        }

        // Getter和Setter方法
        public String getId() { return id; }
        public void setId(String id) { this.id = id; }

        public String getName() { return name; }
        public void setName(String name) { this.name = name; }

        public Integer getAge() { return age; }
        public void setAge(Integer age) { this.age = age; }

        public Double getSalary() { return salary; }
        public void setSalary(Double salary) { this.salary = salary; }

        public Boolean getActive() { return active; }
        public void setActive(Boolean active) { this.active = active; }

        public LocalDate getDate() { return date; }
        public void setDate(LocalDate date) { this.date = date; }

        @Override
        public String toString() {
            return "Person{id='" + id + "', name='" + name + "', age=" + age +
                    ", salary=" + salary + ", active=" + active + ", date=" + date + "}";
        }
    }
}